package ldh.im.fxgui.component.message;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.layout.StackPane;
import javafx.util.Callback;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.data.pojo.ImSession;
import ldh.im.fxgui.handle.IMessageEditorHandler;
import ldh.im.fxgui.component.message.bo.WrapImMessage;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public abstract class BaseMessageListViewHandler implements MessageListViewHandler {

    protected volatile ImSession imSession = null;
    protected Callback<? super BaseMessageListViewHandler, List<WrapImMessage>> loadFrontCallback = null;
    protected Callback<? super BaseMessageListViewHandler, List<WrapImMessage>> loadLastCallback = null;
    protected Callback<ImSession, List<ImMessage>> refreshCallback = null;

    protected BooleanProperty messageSelectProperty = new SimpleBooleanProperty(false);

    protected Integer limitTotal = 500;
    protected boolean isLoading = false;

    private IMessageEditorHandler messageEditorService;
    private StackPane dialogRoot;

    public BaseMessageListViewHandler(IMessageEditorHandler messageEditorService, StackPane dialogRoot) {
        this.messageEditorService = messageEditorService;
        this.dialogRoot = dialogRoot;
    }

    public void setLimitTotal(Integer limitTotal) {
        this.limitTotal = limitTotal;
    }

    @Override
    public boolean canShowMessage(ImMessage message) {
        if (imSession != null) {
            return imSession.getId().equals(message.getSessionId());
        }
        return false;
    }

    @Override
    public void updateMessage(ImMessage message) {
        update(message);
    }

    @Override
    public void updateMessages(List<ImMessage> messages) {
        for (ImMessage imMessage : messages) {
            update(imMessage);
        }
    }

    @Override
    public void deleteMessage(ImMessage message) {
        getItems().remove(WrapImMessage.wrap(message));
    }

    @Override
    public void deleteMessages(List<ImMessage> messages) {
        List<WrapImMessage> wrapImMessages = messages.stream().map(m->WrapImMessage.wrap(m)).collect(Collectors.toList());
        getItems().removeAll(wrapImMessages);
    }

    @Override
    public void setImSession(ImSession imSession) {
        this.imSession = imSession;
    }

    @Override
    public BooleanProperty messageSelectProperty() {
        return messageSelectProperty;
    }

    @Override
    public void refresh() {
        if (refreshCallback != null) {
            refreshCallback.call(getMessageSession());
        }
    }

    @Override
    public ImSession getMessageSession() {
        return imSession;
    }

    @Override
    public IMessageEditorHandler getMessageEditorService() {
        return messageEditorService;
    }

    @Override
    public StackPane getDialogRoot() {
        return dialogRoot;
    }

    @Override
    public void setDialogRoot(StackPane stackPane) {
        this.dialogRoot = stackPane;
    }

    @Override
    public synchronized ImMessage getFirstMessage() {
        if (getItems().size() > 0) {
            return getItems().get(0).getImMessage();
        }
        return null;
    }

    @Override
    public synchronized ImMessage getLastedMessage() {
        if (getItems().size() > 0) {
            return getItems().get(getItems().size() - 1).getImMessage();
        }
        return null;
    }

    @Override
    public synchronized void addLastedMessages(List<ImMessage> messages) {
        addMessages(messages);
    }

    @Override
    public synchronized Set<Long> getMessageIdSet() {
        return getItems().stream().map(m->m.getImMessage().getId()).collect(Collectors.toSet());
    }

    public void refMessage(ImMessage message) {
       messageEditorService.setRefMessage(message);
    }

    public void setLoadFrontCallback(Callback<? super BaseMessageListViewHandler, List<WrapImMessage>> loadFirstCallback) {
        this.loadFrontCallback = loadFirstCallback;
    }

    public void setLoadLastCallback(Callback<? super BaseMessageListViewHandler, List<WrapImMessage>> loadLastCallback) {
        this.loadLastCallback = loadLastCallback;
    }

    public void setRefreshCallback(Callback<ImSession, List<ImMessage>> refreshCallback) {
        this.refreshCallback = refreshCallback;
    }

    protected synchronized int removeMore() {
        if(getItems().size() > limitTotal) {
            int size = getItems().size() - limitTotal;
            if (size < 10) {
                size = 50;
            }
            getItems().remove(0, size);
            return size;
        }
        return 0;
    }

    protected synchronized int removeLastMore() {
        int size = getItems().size();
        if(size > limitTotal) {
            int longSize = size - limitTotal;
            if (longSize < 10) {
                longSize = 50;
            }
            int index = size - longSize;
            getItems().remove(index, size);
            return size - index;
        }
        return 0;
    }

    protected int messageComparator(WrapImMessage message, WrapImMessage message2) {
        if (message == null) return 0;
        if (message2 == null) return 0;
        int t = message.getImMessage().getServerReceiveTime().compareTo(message2.getImMessage().getServerReceiveTime());
        if (t == 0) {
            if (message.getImMessage().getServerId() != null && message2.getImMessage().getServerId() != null) {
                t =  convertServerId(message.getImMessage()).compareTo(convertServerId(message2.getImMessage()));
                if (t == 0) {
                    return message.getImMessage().getServerId().compareTo(message2.getImMessage().getServerId());
                } else {
                    return t;
                }
            }
        }
        return t;
    }

    private Long convertServerId(ImMessage imMessage) {
        try {
            Long.parseLong(imMessage.getServerId());
        } catch (Exception e) {}
        return 0L;
    }
}
